# 使用 __slots__

# 正常情况下，当我们定义有一个 class, 创建了一个 class 的实例后，我们可以给该实例绑定任何属性和方法，这就是动态语言的灵活性。先定义 class
class Student(object):
     pass
# 然后，尝试给实例绑定一个属性
s = Student()
s.name = 'Michael' # 动态绑定一个实例属性
print(s.name)

# 还可以尝试给实例绑定一个方法
def set_age(self, age): # 定义一个函数作为实例方法
    self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
# 调用实例方法
s.set_age(25)
print(s.age) # 测试结果：25

# 但是，给一个实例绑定的方法，对另一个实例是不起作用的：
s1 = Student()
# s1.set_age(25) # 直接报错：AttributeError: 'Student' object has no attribute 'set_age'

# 通常情况下，上面的set_score方法可以直接定义在class中，但是动态绑定运行我们在程序运行的时候，动态的给class加上功能，这在静态语言中无法实现，比如Java。

print('-' * 100)
# 使用__slots__
# 但是，如果我们想要限制实例的属性怎么办？比如，只允许对student实例添加 name 和 age 属性
# 为了达到限制的目的，Python 运行在定义 class 的时候，定义一个特殊的__slots__变量，来限制该class实例能添加的属性：
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
s = Student()
s.name = 'Bob'
s.age = 18
# s.score = 99 # 会报错，因为score属性不在__slots__中定义中，所以不能添加该属性，错误信息：AttributeError: 'Student' object has no attribute 'score'
